/**
 * 反射应用场景之一：根据配置文件调用相应的类和方法，框架中经常用到
 * 反射应用场景之二：越过泛型检查
 */
package com.example.reflect;

import java.io.File;
import java.io.FileInputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Properties;

public class ReflectPractice {

    public static void main(String[] args) throws Exception {
        /*----------配置文件中灵活配置类和方法----------*/
        //从spring.txt中获取类名称和方法名称
        File springConfigFile = new File(ReflectPractice.class.getResource("spring.txt").getFile());
        /*等效替代
        String fs=System.getProperty("file.separator");
        File springConfigFile = new File("src"+fs+"com"+fs+"example"+fs+"reflect"+fs+"spring.txt");*/

        Properties springConfig = new Properties();
        springConfig.load(new FileInputStream(springConfigFile));
        String className = (String) springConfig.get("class");
        String methodName = (String) springConfig.get("method");
        System.out.println(className);
        //根据类名称获取类对象
        Class clazz = Class.forName(ReflectPractice.class.getPackage().getName() + "." + className);
        //根据方法名称，获取方法对象
        Method m = clazz.getMethod(methodName);
        //获取构造器
        Constructor c = clazz.getConstructor();
        //根据构造器，实例化出对象
        Object obj = c.newInstance();
        //调用对象的指定方法
        m.invoke(obj);

        /*----------越过泛型检查----------*/
        ArrayList<String> list = new ArrayList<>();
        list.add("this");
        list.add("is");
        //List.add(5);报错

        //获取ArrayList的Class对象，反向的调用add()方法，添加数据
        Class listClass = list.getClass();
        //获取add()方法
        Method mAdd = listClass.getMethod("add", Object.class);
        //调用add()方法
        mAdd.invoke(list, 5);
        //遍历集合
        for (Object object : list) {
            System.out.println(object);
        }
    }
}
